<template>
  <div class="code-generator-container">
    <el-card class="box-card">
      <template #header>
        <div class="list-header">
          <h2>代码生成</h2>
          <div class="header-actions">
            <el-tooltip content="关闭" placement="bottom">
              <el-button
                  type="info"
                  @click="$emit('closeCodeGenerator')"
                  size="small"
                  class="icon-btn"
              >
                <el-icon><Close /></el-icon>
              </el-button>
            </el-tooltip>
          </div>
        </div>
      </template>

      <div class="content-layout">
        <!-- 左侧表单 -->
        <div class="form-container">
          <el-form :model="generateForm" class="search-form" :class="{ 'form-disabled': progressVisible }">
            <el-form-item label="地址名称" label-width="100px">
              <el-select
                v-model="generateForm.addressName"
                placeholder="请选择地址"
                filterable
                clearable
                @change="handleAddressChange"
                style="width: 100%"
                :disabled="progressVisible"
              >
                <el-option
                  v-for="addr in addressList"
                  :key="addr.id"
                  :label="addr.name"
                  :value="addr.id"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="库名" label-width="100px">
              <el-select
                v-model="generateForm.dbName"
                placeholder="请选择库名"
                filterable
                clearable
                @change="handleDbChange"
                style="width: 100%"
                :disabled="progressVisible"
              >
                <el-option
                  v-for="db in dbOptions"
                  :key="db"
                  :label="db"
                  :value="db"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="表名" label-width="100px">
              <el-select
                v-model="generateForm.tableName"
                placeholder="请选择表名"
                filterable
                clearable
                :disabled="!generateForm.dbName || progressVisible"
                style="width: 100%"
              >
                <el-option
                  v-for="table in tableOptions"
                  :key="table"
                  :label="table"
                  :value="table"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="包名" label-width="100px">
              <el-input
                v-model="generateForm.packageName"
                placeholder="请输入包名，例如：com.example"
                :disabled="progressVisible"
                style="width: 100%"
              />
            </el-form-item>
            <el-form-item label="模块名" label-width="100px">
              <el-input
                  v-model="generateForm.moduleName"
                  placeholder="模块名，例如：common"
                  :disabled="progressVisible"
                  style="width: 100%"
              />
            </el-form-item>
            <el-form-item label="作者" label-width="100px">
              <el-input
                v-model="generateForm.author"
                placeholder="请输入作者名称"
                :disabled="progressVisible"
                style="width: 100%"
              />
            </el-form-item>
            <el-form-item label-width="100px">
              <div class="button-group">
                <el-button type="primary" @click="handleGenerate" :loading="tableLoading || progressVisible" :disabled="tableLoading || progressVisible" :icon="Download">生成</el-button>
                <el-button @click="resetForm" :disabled="tableLoading || progressVisible" :icon="RefreshRight">重置</el-button>
              </div>
            </el-form-item>
          </el-form>
        </div>

        <!-- 右侧进度条 -->
        <div class="progress-container">
          <el-progress
            type="circle"
            :percentage="progressPercentage"
            :status="progressPercentage === 100 ? 'success' : ''"
            :stroke-width="8"
          >
            <template #default>
              <div class="progress-info">
                <div class="progress-text">{{ progressPercentage }}%</div>
                <div class="progress-count">{{ generatedCount }}/{{ totalCount || 100 }}</div>
              </div>
            </template>
          </el-progress>
          <div class="progress-label">
            {{ progressVisible ? '正在生成代码，请稍候...' : '等待生成代码' }}
          </div>

          <!-- 下载按钮，仅在生成完成后显示 -->
          <div v-if="downloadUrl" class="download-section">
            <el-button type="success" @click="downloadFile" :icon="Download">
              下载代码
            </el-button>
          </div>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import {nextTick, onMounted, onUnmounted, reactive, ref} from 'vue'
import {Close, Download, RefreshRight} from '@element-plus/icons-vue'
import api from '@/api'
import axios from 'axios'
import {ElMessage} from 'element-plus'
import {useTokenStore} from '@/stores/token'

// 表单数据
const generateForm = reactive({
  addressName: '',
  id: '',
  host: '',
  port: '',
  userName: '',
  passWord: '',
  dbName: '',
  tableName: '',
  packageName: '',
  moduleName: '',
  author: ''
})

// 数据
const addressList = ref([])
const dbOptions = ref([])
const tableOptions = ref([])
const selectedAddress = ref(null)
const tableLoading = ref(false)
const generatedCount = ref(0)
const totalCount = ref(100)  // 设置默认总数为100
const progressVisible = ref(false)  // 控制生成过程中的状态
const progressPercentage = ref(0)
const downloadUrl = ref('')  // 用于存储下载链接
const downloadFilename = ref('generated-code.zip')  // 用于存储下载文件名

// 获取地址列表
const fetchAddressList = async () => {
  try {
    const data = {
      deleted: 0
    }
    const response = await api.binlog.list(data, 1, 1000)
    if (response.code === 200) {
      addressList.value = response.data.records || []
    }
  } catch (error) {
    console.error('获取地址列表失败:', error)
    ElMessage.error('获取地址列表失败')
  }
}

// 获取数据库列表
const fetchDatabaseList = async () => {
  if (!selectedAddress.value) return

  try {
    const { id, host, port, userName, passWord } = selectedAddress.value
    const response = await api.binlog.getDataBaseList({ id, host, port, userName, passWord })

    if (response.code === 200) {
      dbOptions.value = response.data || []
      // 如果地址有预设的dbName，则自动选中
      if (selectedAddress.value.dbName) {
        generateForm.dbName = selectedAddress.value.dbName
      }
    } else {
      ElMessage.error(response.msg || '获取数据库列表失败')
      dbOptions.value = []
    }
  } catch (error) {
    console.error('获取数据库列表失败:', error)
    ElMessage.error('获取数据库列表失败')
    dbOptions.value = []
  }
}

// 获取表列表
const fetchTableList = async (dbName) => {
  if (!selectedAddress.value || !dbName) {
    tableOptions.value = []
    return
  }

  try {
    const { id, host, port, userName, passWord } = selectedAddress.value
    const response = await api.binlog.getDataTableList({
      id,
      host,
      port,
      userName,
      passWord,
      dbName
    })

    if (response.code === 200) {
      tableOptions.value = response.data || []
    } else {
      ElMessage.error(response.msg || '获取表列表失败')
      tableOptions.value = []
    }
  } catch (error) {
    console.error('获取表列表失败:', error)
    ElMessage.error('获取表列表失败')
    tableOptions.value = []
  }
}

// 处理地址选择变化
const handleAddressChange = (addressId) => {
  if (!addressId) {
    generateForm.dbName = ''
    generateForm.tableName = ''
    generateForm.host = ''
    generateForm.port = ''
    generateForm.userName = ''
    generateForm.passWord = ''
    generateForm.id = ''
    dbOptions.value = []
    tableOptions.value = []
    selectedAddress.value = null
    return
  }

  selectedAddress.value = addressList.value.find(addr => addr.id === addressId)
  if (selectedAddress.value) {
    // 设置连接信息到generateForm
    generateForm.host = selectedAddress.value.host
    generateForm.port = selectedAddress.value.port
    generateForm.userName = selectedAddress.value.userName
    generateForm.passWord = selectedAddress.value.passWord
    generateForm.id = selectedAddress.value.id

    fetchDatabaseList().then(() => {
      // 仅在地址变化时设置预设库名
      if (selectedAddress.value?.dbName && dbOptions.value.includes(selectedAddress.value.dbName)) {
        generateForm.dbName = selectedAddress.value.dbName
        // 获取表列表
        fetchTableList(selectedAddress.value.dbName).then(() => {
          // 仅在地址初次选择时设置预设表名
          if (selectedAddress.value?.tableName && tableOptions.value.includes(selectedAddress.value.tableName)) {
            generateForm.tableName = selectedAddress.value.tableName
          }
        })
      }
    })
  }
}

// 处理数据库选择变化
const handleDbChange = async (dbName) => {
  // 立即清空表名和表选项
  generateForm.tableName = ''
  tableOptions.value = []

  // 确保DOM更新完成
  await nextTick()

  // 如果选择了有效的库名且有选中的地址，则获取表列表
  if (dbName && selectedAddress.value) {
    try {
      await fetchTableList(dbName)
    } catch (error) {
      console.error('获取表列表失败:', error)
      ElMessage.error({
        message: `获取表列表失败: ${error.message || '未知错误'}`,
        duration: 3000
      })
    }
  }
}

// 生成代码
const generateCode = async () => {
  tableLoading.value = true
  try {
    const data = {
      id: generateForm.id,
      addressName: generateForm.addressName,
      host: generateForm.host,
      port: generateForm.port,
      userName: generateForm.userName,
      passWord: generateForm.passWord,
      dbName: generateForm.dbName,
      tableName: generateForm.tableName,
      packageName: generateForm.packageName,
      moduleName: generateForm.moduleName,
      author: generateForm.author
    }

    console.log('开始生成代码，请求参数:', data)

    // 使用axios直接调用API，以便获取完整的响应对象（包括headers）
    const url = `/api/mybatisPlus/generator`
    
    console.log('请求URL:', url)
    
    // 获取token
    const tokenStore = useTokenStore()
    const token = tokenStore.token
    
    console.log('当前Token:', token ? '存在' : '不存在')
    
    const response = await axios({
      method: 'post',
      url: url,
      data: data,
      responseType: 'blob',
      headers: {
        'Accept': 'application/octet-stream',
        'Content-Type': 'application/json',
        'Authorization': token ? `Bearer ${token}` : ''
      },
      // 确保获取完整的响应，即使状态码不是2xx
      validateStatus: () => true
    })

    console.log('生成代码响应状态:', response.status)
    
    // 检查响应状态
    if (response.status !== 200) {
      // 如果响应不是成功状态
      if (response.data instanceof Blob) {
        // 尝试读取错误信息
        const reader = new FileReader()
        reader.onload = function() {
          try {
            const errorData = JSON.parse(reader.result)
            ElMessage.error(errorData.msg || '代码生成失败')
          } catch (e) {
            ElMessage.error(`代码生成失败，状态码: ${response.status}`)
          }
          // 重置状态
          progressVisible.value = false
          tableLoading.value = false
        }
        reader.readAsText(response.data)
      } else {
        ElMessage.error(`代码生成失败，状态码: ${response.status}`)
        progressVisible.value = false
        tableLoading.value = false
      }
      return
    }

    // 获取文件名
    downloadFilename.value = 'generated-code.zip'
    const contentDisposition = response.headers['content-disposition']
    if (contentDisposition) {
      console.log('Content-Disposition:', contentDisposition)
      const filenameMatch = contentDisposition.match(/filename=([^;]+)/)
      if (filenameMatch && filenameMatch[1]) {
        downloadFilename.value = filenameMatch[1].replace(/"/g, '')
        console.log('解析到的文件名:', downloadFilename.value)
      }
    }

    // 获取内容类型
    const contentType = response.headers['content-type'] || 'application/octet-stream'
    console.log('Content-Type:', contentType)

    // 创建Blob对象 - 使用后端返回的内容类型
    const blob = new Blob([response.data], { type: contentType })

    // 创建下载链接
    downloadUrl.value = window.URL.createObjectURL(blob)

    // 立即完成进度
    completeProgress()

    ElMessage.success('代码生成成功，请点击下载按钮获取')
  } catch (error) {
    console.error('代码生成失败:', error)
    // 显示详细错误信息
    let errorMessage = '代码生成失败'
    
    if (error.response) {
      console.error('错误响应:', error.response)
      // 尝试从响应中获取错误信息
      if (error.response.data instanceof Blob) {
        // 如果错误响应是Blob，尝试读取它
        const reader = new FileReader()
        reader.onload = function() {
          try {
            const errorData = JSON.parse(reader.result)
            ElMessage.error(errorData.msg || errorMessage)
          } catch (e) {
            ElMessage.error(`${errorMessage}: ${error.response.status}`)
          }
        }
        reader.readAsText(error.response.data)
      } else {
        // 直接使用错误信息
        errorMessage = error.response.data?.msg || `${errorMessage}: ${error.response.status}`
        ElMessage.error(errorMessage)
      }
    } else if (error.request) {
      // 请求已发送但没有收到响应
      console.error('请求未收到响应:', error.request)
      ElMessage.error('服务器未响应，请检查网络连接')
    } else {
      // 设置请求时发生的错误
      console.error('请求错误:', error.message)
      ElMessage.error(error.message || errorMessage)
    }

    // 停止进度更新并重置进度条状态
    stopProgress()
    progressVisible.value = false
  } finally {
    tableLoading.value = false
  }
}

// 下载文件
const downloadFile = () => {
  if (!downloadUrl.value) {
    ElMessage.warning('没有可下载的文件')
    return
  }

  // 创建一个临时链接
  const link = document.createElement('a')
  link.href = downloadUrl.value
  link.download = downloadFilename.value || `${generateForm.tableName || 'generated'}-code.zip`
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

// 模拟进度更新
const progressInterval = ref(null)

// 立即完成进度
const completeProgress = () => {
  // 清除可能存在的进度定时器
  if (progressInterval.value) {
    clearInterval(progressInterval.value)
    progressInterval.value = null
  }

  // 立即设置为100%完成
  generatedCount.value = totalCount.value
  progressPercentage.value = 100

  // 延迟关闭进度条状态
  setTimeout(() => {
    progressVisible.value = false
  }, 1000)
}

const simulateProgress = () => {
  // 清除可能存在的旧定时器
  if (progressInterval.value) {
    clearInterval(progressInterval.value)
  }

  let currentCount = 0
  progressInterval.value = setInterval(() => {
    currentCount += Math.floor(Math.random() * 5) + 1
    if (currentCount >= totalCount.value) {
      currentCount = totalCount.value
      clearInterval(progressInterval.value)
      progressInterval.value = null

      // 生成完成后，延迟关闭进度条状态
      setTimeout(() => {
        progressVisible.value = false
      }, 1000)
    }
    generatedCount.value = currentCount
    progressPercentage.value = Math.floor((currentCount / totalCount.value) * 100)
  }, 200)
}

// 停止进度更新
const stopProgress = () => {
  if (progressInterval.value) {
    clearInterval(progressInterval.value)
    progressInterval.value = null
  }
  // 重置进度
  generatedCount.value = 0
  progressPercentage.value = 0
}

// 处理生成
const handleGenerate = () => {
  // 验证必填字段
  if (!generateForm.addressName) {
    ElMessage.warning('请选择地址名称')
    return
  }

  if (!generateForm.dbName) {
    ElMessage.warning('请选择库名')
    return
  }

  if (!generateForm.tableName) {
    ElMessage.warning('请选择表名')
    return
  }

  if (!generateForm.packageName) {
    ElMessage.warning('请输入包名')
    return
  }
  if (!generateForm.moduleName) {
    ElMessage.warning('请输入模块名')
    return
  }

  // 停止可能存在的进度更新
  stopProgress()

  // 重置进度数据和下载链接
  generatedCount.value = 0
  progressPercentage.value = 0
  progressVisible.value = true
  downloadUrl.value = ''

  // 调用API生成代码
  generateCode()
}

// 重置表单
const resetForm = () => {
  Object.assign(generateForm, {
    id: '',
    addressName: '',
    host: '',
    port: '',
    userName: '',
    passWord: '',
    dbName: '',
    tableName: '',
    packageName: '',
    author: '',
    moduleName: ''
  })
  dbOptions.value = []
  tableOptions.value = []
  selectedAddress.value = null
  downloadUrl.value = ''
  downloadFilename.value = 'generated-code.zip'
}

// 组件挂载时获取地址列表，并设置进度条初始状态
onMounted(() => {
  fetchAddressList()
  
  // 设置进度条初始状态
  generatedCount.value = 0
  progressPercentage.value = 0
})

// 组件卸载时清除定时器
onUnmounted(() => {
  // 清除进度更新定时器
  if (progressInterval.value) {
    clearInterval(progressInterval.value)
    progressInterval.value = null
  }
})
</script>

<style scoped>
.code-generator-container {
  padding: 20px;
}

.box-card {
  margin-bottom: 20px;
  position: relative;
}

.list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.list-header h2 {
  margin: 0;
  font-size: 18px;
  color: #303133;
}

.header-actions {
  display: flex;
  gap: 10px;
}

.icon-btn {
  width: 32px;
  height: 32px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  transition: all 0.2s ease;
}

.icon-btn:hover {
  transform: scale(1.1);
}

.icon-btn .el-icon {
  font-size: 16px;
}

/* 左右布局 */
.content-layout {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.form-container {
  flex: 1;
  min-width: 300px;
}

.progress-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px;
  min-width: 250px;
  border-left: 1px solid #ebeef5;
}

.el-form {
  transition: opacity 0.3s ease;
}

.progress-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.progress-text {
  font-size: 20px;
  font-weight: bold;
  color: #409EFF;
}

.progress-count {
  font-size: 14px;
  color: #606266;
  margin-top: 5px;
}

.progress-label {
  margin-top: 15px;
  font-size: 16px;
  color: #606266;
}

/* 下载按钮区域 */
.download-section {
  margin-top: 20px;
  text-align: center;
}

/* 表单禁用样式 */
.form-disabled {
  opacity: 0.7;
  pointer-events: none;
}

/* 表单样式 */
.search-form .el-form-item {
  margin-bottom: 20px;
}

.button-group {
  display: flex;
  justify-content: flex-start;
  gap: 20px;
  margin-top: 10px;
}

@media screen and (max-width: 992px) {
  .content-layout {
    flex-direction: column;
  }
  
  .progress-container {
    border-left: none;
    border-top: 1px solid #ebeef5;
    padding-top: 30px;
    margin-top: 10px;
  }
}

@media screen and (max-width: 768px) {
  .code-generator-container {
    padding: 10px;
  }

  .icon-btn {
    width: 28px;
    height: 28px;
  }

  .icon-btn .el-icon {
    font-size: 14px;
  }
  
  .progress-text {
    font-size: 18px;
  }
  
  .progress-count {
    font-size: 12px;
  }
  
  .progress-label {
    font-size: 14px;
  }
}
</style>